﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using MemoryDuosControl;

namespace MemoryDuosInterfaz
{
    public class TableroMultijugador
    {
        internal List<Coordenadas> destapadas;
        private int fallos;

        private int maxParejas;

        public int parejasConsecutivas;

        public int Alto { get; set; }

        public int Ancho { get; set; }

        public Button[,] ArrayBotones { get; set; }

        public bool[,] EstadoDestapadaTablero { get; set; }

        public EstadoTablero Estado { get; set; }

        public string Galería { get; set; }

        public bool[,] HayImagen { get; set; }

        public Image[,] Imagenes { get; set; }

        public List<Image> listaImagenes { get; set; }

        public int[,] codigosImagenes { get; set; }

        public int[,] idUsuarioDestapa { get; set; }


        public TableroMultijugador()
        {
            Ancho = 6;
            Alto = 7;
            idUsuarioDestapa = new int[Alto, Ancho];
            codigosImagenes = new int[Alto, Ancho];
            Imagenes = new Image[Alto, Ancho];
            EstadoDestapadaTablero = new Boolean[Alto, Ancho];
            HayImagen = new Boolean[Alto, Ancho];
            fallos = 0;
            maxParejas = 0;
            parejasConsecutivas = 0;
            destapadas = new List<Coordenadas>();
        }

        public TableroMultijugador(EstadoTablero estado)
            : this()
        {
            Estado = estado;
            RellenarTablero(Estado);
            RellenarDestapadas(Estado);
        }

        private void RellenarDestapadas(EstadoTablero estado)
        {
            destapadas.Clear();
            if (estado.Destapadas != null)
            {
                foreach (var cas in estado.Destapadas)
                {
                    destapadas.Add(new Coordenadas(cas.y, cas.x));
                }
            }
        }

        private void RellenarTablero(EstadoTablero estado)
        {
            this.Galería = estado.Galeria_Nombre;
            var lista = AccesoGaleria.LeerGalerías(estado.Galeria_Nombre);
            if (estado.Estado != null)
            {
                Parallel.ForEach(estado.Estado, cas =>
                {
                    Galería gal = lista.Find(g => g.Codigo == cas.idImagen);
                    Image img = AccesoGaleria.LeerDeServidor(gal);
                    SetImagen(cas.y, cas.x, img, cas.idImagen);
                    SetEstado(new Coordenadas(cas.y, cas.x), cas.Estado);
                });
            }
        }

        public void ActualizarEstadoPartida()
        {
            Controlador.Instance.PartidaActual = Controlador.Instance.UsuarioActual.ObtenerPartidaID(Controlador.Instance.PartidaActual.Codigo);
            EstadoTablero estado = Controlador.Instance.UsuarioActual.ObtenerTablero(Controlador.Instance.PartidaActual.Codigo);
            int pos = 0;
            RellenarDestapadas(estado);
            foreach (CasillaTablero cas in estado.Estado)
            {
                SetImagen(cas.y, cas.x, GetImagen(new Coordenadas(cas.y, cas.x)), cas.idImagen);
                SetEstado(new Coordenadas(cas.y, cas.x), cas.Estado);
            }
        }

        public void almacenarCoordenadasParejasLista(Coordenadas coordenadas)
        {
            destapadas.Add(coordenadas);
        }

        public bool comprobarCartasLista()
        {
            if (destapadas.Count == 2)
            {
                int imagenCarta1 = this.GetIdImagen(destapadas.ElementAt(0));
                int imagenCarta2 = this.GetIdImagen(destapadas.ElementAt(1));
                // comprobamos si las cartas destapadas son iguales
                if (imagenCarta1 != (imagenCarta2))
                {
                    return false;
                }
                else
                    parejasConsecutivas++;
            }
            return true;
        }

        public void destaparCarta(object sender, EventArgs e, Timer timerCartas, Timer timerInactividad, TimeSpan tiempo, Form partida)
        {
            Coordenadas coordenadas = obtenerCoordenadaBoton((Button)sender);
            // destapamos la carta si su estado es false
            if (timerCartas.Enabled == true)
                return;
            if (!this.GetEstado(coordenadas) && destapadas.Count <= 2)
            {
                almacenarCoordenadasParejasLista(coordenadas);
            }
            if (!this.GetEstado(coordenadas) && destapadas.Count == 1)
            {
                ((Button)sender).BackgroundImage = this.GetImagen(coordenadas);
                this.SetEstado(coordenadas, true);
                timerInactividad.Start();
            }
            if (!this.GetEstado(coordenadas) && destapadas.Count == 2)
            {
                ((Button)sender).BackgroundImage = this.GetImagen(coordenadas);
                timerInactividad.Stop();

                if (!comprobarCartasLista()) { timerCartas.Start(); } else { this.SetEstado(coordenadas, true); destapadas.Clear(); }
            }
            if (this.EsFinPartida())
            {
                //EstadisticasPartida fin = new EstadisticasPartida(tiempo, parejasConsecutivas, fallos, this);
                // fin.ShowDialog(partida);
            }
        }

        public bool EsFinPartida()
        {
            List<Boolean> Lista = EstadoDestapadaTablero.Cast<Boolean>().ToList();
            bool existe = Lista.Exists(r => r == false);
            return !existe;
        }

        public bool esValido(int alto, int ancho)
        {
            //Controlar que no nos salimos del tablero
            try
            {
                var b = HayImagen[alto, ancho];
                var c = Imagenes[alto, ancho];
                var d = EstadoDestapadaTablero[alto, ancho];
                return true;
            }
            catch (IndexOutOfRangeException)
            {
                return false;
            }
        }

        public void FinalizarPartida(string estadoTablero)
        {
            if (Controlador.Instance.PartidaActual.Nick_1.Equals(Controlador.Instance.UsuarioActual.Nick))
            {
                int puntuacionMia = Controlador.Instance.PartidaActual.Puntuacion_1.Value;
                int puntuacionSuya = Controlador.Instance.PartidaActual.Puntuacion_2.Value;
                int mayor = puntuacionMia > puntuacionSuya ? puntuacionMia : puntuacionSuya;
                int IDGana = puntuacionMia > puntuacionSuya ? Controlador.Instance.PartidaActual.Usuario_1 : Controlador.Instance.PartidaActual.Usuario_2;
                Controlador.Instance.UsuarioActual.FinalizarPartida("", mayor, IDGana);
            }
            else if (Controlador.Instance.PartidaActual.Nick_2.Equals(Controlador.Instance.UsuarioActual.Nick))
            {
                int puntuacionMia = Controlador.Instance.PartidaActual.Puntuacion_2.Value;
                int puntuacionSuya = Controlador.Instance.PartidaActual.Puntuacion_1.Value;
                int mayor = puntuacionMia > puntuacionSuya ? puntuacionMia : puntuacionSuya;
                int IDGana = puntuacionMia > puntuacionSuya ? Controlador.Instance.PartidaActual.Usuario_2 : Controlador.Instance.PartidaActual.Usuario_1;
                Controlador.Instance.UsuarioActual.FinalizarPartida("", mayor, IDGana);
            }
        }

        public bool GetEstado(Coordenadas coordenadas)
        {
            if (esValido(coordenadas.Y, coordenadas.X))
            {
                return EstadoDestapadaTablero[coordenadas.Y, coordenadas.X];
            }
            return false;
        }

        public Image GetImagen(Coordenadas coordenadas)
        {
            if (esValido(coordenadas.Y, coordenadas.X))
            {
                return Imagenes[coordenadas.Y, coordenadas.X];
            }
            return null;
        }

        public int GetIdImagen(Coordenadas coordenadas)
        {
            if (esValido(coordenadas.Y, coordenadas.X))
            {
                return codigosImagenes[coordenadas.Y, coordenadas.X];
            }
            return 0;
        }

        public Coordenadas obtenerCoordenadaBoton(Button boton)
        {
            for (int i = 0; i < ArrayBotones.GetLength(0); i++)
            {
                for (int j = 0; j < ArrayBotones.GetLength(1); j++)
                {
                    if (boton.Equals(ArrayBotones[i, j]))
                    {
                        return new Coordenadas(i, j);
                    }
                }
            }
            return null;
        }

        public void PausarPartida(TimeSpan tiempo)
        {
            // throw new NotImplementedException();
        }

        public void SetEstado(Coordenadas coordenadas, bool estadoNuevo)
        {
            if (esValido(coordenadas.Y, coordenadas.X))
            {
                idUsuarioDestapa[coordenadas.Y, coordenadas.X] = Controlador.Instance.UsuarioActual.ID;
                EstadoDestapadaTablero[coordenadas.Y, coordenadas.X] = estadoNuevo;
            }
        }

        public void SetImagen(int alto, int ancho, Image imagen, int id)
        {
            if (esValido(alto, ancho))
            {
                Imagenes[alto, ancho] = imagen;
                HayImagen[alto, ancho] = true;
                codigosImagenes[alto, ancho] = id;
            }
        }

        public bool SonIguales(Coordenadas coordenadas1, Coordenadas coordenadas2)
        {
            //Retorna si dos imagenes son iguales
            if (esValido(coordenadas1.Y, coordenadas1.X) && esValido(coordenadas2.Y, coordenadas2.X))
            {
                if (Imagenes[coordenadas1.Y, coordenadas1.X].Equals(Imagenes[coordenadas2.Y, coordenadas2.X]))
                    return true;
            }

            return false;
        }

        public void TaparCarta(Coordenadas c1)
        {
            ArrayBotones[c1.Y, c1.X].BackgroundImage = MemoryDuosInterfaz.Properties.Resources.MEMORYDUOS;
            this.SetEstado(c1, false);
        }

        public void TaparCartas(Coordenadas c1, Coordenadas c2)
        {
            ArrayBotones[c1.Y, c1.X].BackgroundImage = MemoryDuosInterfaz.Properties.Resources.MEMORYDUOS;
            ArrayBotones[c2.Y, c2.X].BackgroundImage = MemoryDuosInterfaz.Properties.Resources.MEMORYDUOS;
            ArrayBotones[c1.Y, c1.X].BackColor = Color.White;
            ArrayBotones[c2.Y, c2.X].BackColor = Color.White;
            this.SetEstado(c1, false);
            this.SetEstado(c2, false);
        }

        public void TaparCartasDiferentes(Timer timerCartas)
        {
            if (destapadas.Count == 2)
            TaparCartas(destapadas.ElementAt(0), destapadas.ElementAt(1)); destapadas.Clear(); timerCartas.Stop();
        }

        public void InicializarTablero(List<Image> imagenes, List<int> codigos)
        {
            Random random = new Random();
            int j = 0;
            foreach (Image img in imagenes)
            {
                for (int i = 0; i <= 1; i++)
                {
                    int alto1 = random.Next(0, Alto);
                    int ancho1 = random.Next(0, Ancho);
                    if (!HayImagen[alto1, ancho1])
                    {
                        SetImagen(alto1, ancho1, img, codigos.ElementAt(j));
                    }
                    else i--;
                }
                j++;
            }
        }

        public List<CasillaTablero> GuardarEstado()
        {
            if (destapadas.Count == 1) { TaparCarta(destapadas.ElementAt(0)); } // si cierro la
            // ventana se tapa la unica carta destapada
            List<CasillaTablero> lista = new List<CasillaTablero>();
            for (int i = 0; i < Alto; i++)
            {
                for (int j = 0; j < Ancho; j++)
                {
                    lista.Add(new CasillaTablero
                    {
                        x = j,
                        y = i,
                        Estado = GetEstado(new Coordenadas(i, j)),
                        idImagen = codigosImagenes[i, j],
                        idUsuario = idUsuarioDestapa[i, j]
                    });
                }
            }
            return lista;
        }

        private List<Coordenadas> ObtenerListaCoordenadasAcertadas(List<Tuple<int, int, int>> lista)
        {
            var devolver = new List<Coordenadas>();
            foreach (var par in lista)
            {
                devolver.Add(new Coordenadas(par.Item1, par.Item2));
            }
            return devolver;
        }

        public int CalcularPuntuacion()
        {
            if (this.parejasConsecutivas == 1) return 10;
            return 10 + this.parejasConsecutivas;
        }

        public bool EsMiTurno()
        {
            // this.ActualizarEstadoPartida();
            return Controlador.Instance.PartidaActual.Turno.Equals(Controlador.Instance.UsuarioActual.ID);
        }

        public List<CasillaTablero> ObtenerListaDestapadas()
        {
            var lista = new List<CasillaTablero>();
            foreach (var cas in destapadas)
            {
                lista.Add(new CasillaTablero { x = cas.X, y = cas.Y, Estado = false, idUsuario = Controlador.Instance.UsuarioActual.ID });
            }
            return lista;
        }

        public Coordenadas EncontrarPrimeraTapada()
        {
            for (int i = 0; i < EstadoDestapadaTablero.GetLength(0); i++)
            {
                for (int j = 0; j < EstadoDestapadaTablero.GetLength(1); j++)
                {
                    if (EstadoDestapadaTablero[i, j] == false)
                    {
                        return new Coordenadas(i, j);
                    }
                }
            }
            return null;
        }

        private Coordenadas encontrarSiguienteIgual(Coordenadas cord1)
        {
            for (int i = 0; i < ArrayBotones.GetLength(0); i++)
            {
                for (int j = 0; j < ArrayBotones.GetLength(1); j++)
                {
                    bool destapada = EstadoDestapadaTablero[i, j];
                    bool imagenes = codigosImagenes[cord1.Y, cord1.X].Equals(codigosImagenes[i, j]);
                    bool coordenadas = !(i == cord1.Y && j == cord1.X);
                    if (!destapada && imagenes && coordenadas)
                    {
                        return new Coordenadas(i, j);
                    }
                }
            }
            return null;
        }

        public void destaparPareja()
        {
            Coordenadas c1 = EncontrarPrimeraTapada();
            Coordenadas cord2 = encontrarSiguienteIgual(c1);
           // parejasConsecutivas++;
           // CalcularPuntuacion();
            ArrayBotones[c1.Y, c1.X].BackgroundImage = Imagenes[c1.Y, c1.X];
            SetEstado(c1, true);
            SetEstado(cord2, true);
            // ArrayBotones[cord1.Y, cord1.X].BackColor = Color.Green;
            ArrayBotones[cord2.Y, cord2.X].BackgroundImage = Imagenes[cord2.Y, cord2.X];
            // ArrayBotones[cord2.Y, cord2.X].BackColor = Color.Green; destapadas.Add(cord1);
            //
            //
            //
            //
            //
            //
            //
         ///   destapadas.Add(cord2);
        }

        public void destaparCartaIgual()
        {
            Coordenadas c1 = destapadas.ElementAt(0);
            Coordenadas c2 = encontrarSiguienteIgual(c1);
            //parejasConsecutivas++;
            //CalcularPuntuacion();
            SetEstado(c2, true);
            ArrayBotones[c1.Y, c1.X].BackgroundImage = Imagenes[c1.Y, c1.X];
   
           ArrayBotones[c2.Y, c2.X].BackgroundImage = Imagenes[c2.Y, c2.X];
            //destapadas.Add(c2);
           //SetEstado(c1, true);
            
        }
    }
}
